#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <atomic>

// ==================== 原始正确实现 ====================
std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void wait_for_signal()
{
    std::unique_lock<std::mutex> lock(mtx);
    while (!ready)
    { // while 循环 + 条件判断
        // 等待锁就绪
        std::cout << "t1等待信号" << std::endl;
        cv.wait(lock);
    }
    // 执行需要在 ready 为 true 后的操作
    std::cout << "t1收到信号并执行" << std::endl;
}

void send_signal()
{
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 确保t1先等待
    std::lock_guard<std::mutex> lock(mtx);
    ready = true; // 使条件满足
    std::cout << "发送信号去通知t1" << std::endl;
    cv.notify_one(); // 取消注释以正确通知
}

// ==================== 虚假信号唤醒演示 ====================
std::mutex spurious_mtx;
std::condition_variable spurious_cv;
bool spurious_ready = false;
std::atomic<bool> spurious_demo_running{true};

void demonstrate_spurious_wakeup()
{
    std::cout << "\n=== 虚假信号唤醒演示 ===" << std::endl;
    std::cout << "问题：使用if而不是while检查条件，可能导致虚假唤醒问题" << std::endl;
    
    // 错误的实现：使用if而不是while
    auto spurious_waiter = []() {
        std::unique_lock<std::mutex> lock(spurious_mtx);
        std::cout << "[虚假唤醒] 等待线程开始等待..." << std::endl;
        
        // 错误：使用if而不是while！
        if (!spurious_ready) {
            std::cout << "[虚假唤醒] 进入等待状态" << std::endl;
            spurious_cv.wait(lock);
            // 这里可能因为虚假唤醒而被唤醒，但条件可能仍然为false
            std::cout << "[虚假唤醒] 被唤醒了！条件是否满足: " << spurious_ready << std::endl;
        }
        
        if (spurious_ready) {
            std::cout << "[虚假唤醒] 条件满足，执行任务" << std::endl;
        } else {
            std::cout << "[虚假唤醒] ⚠️  虚假唤醒！条件不满足但被唤醒了！" << std::endl;
        }
    };
    
    // 模拟虚假唤醒的发送者
    auto spurious_notifier = []() {
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
        
        // 第一次：不设置条件，直接通知（模拟虚假唤醒）
        {
            std::lock_guard<std::mutex> lock(spurious_mtx);
            std::cout << "[虚假唤醒] 发送虚假通知（条件仍为false）" << std::endl;
            spurious_cv.notify_one();
        }
        
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        
        // 第二次：正确设置条件并通知
        {
            std::lock_guard<std::mutex> lock(spurious_mtx);
            spurious_ready = true;
            std::cout << "[虚假唤醒] 发送正确通知（条件设为true）" << std::endl;
            spurious_cv.notify_one();
        }
    };
    
    std::thread t1(spurious_waiter);
    std::thread t2(spurious_notifier);
    
    t1.join();
    t2.join();
    
    // 重置状态
    spurious_ready = false;
    std::cout << "[虚假唤醒] 演示结束\n" << std::endl;
}

// ==================== 信号量丢失演示 ====================
std::mutex lost_mtx;
std::condition_variable lost_cv;
bool lost_ready = false;

void demonstrate_lost_signal()
{
    std::cout << "=== 信号量丢失演示 ===" << std::endl;
    std::cout << "问题：发送信号时没有线程在等待，导致信号丢失" << std::endl;
    
    // 信号丢失的发送者（先于等待者执行）
    auto lost_signal_sender = []() {
        std::cout << "[信号丢失] 发送者线程启动" << std::endl;
        
        // 立即发送信号（此时还没有线程在等待）
        {
            std::lock_guard<std::mutex> lock(lost_mtx);
            lost_ready = true;
            std::cout << "[信号丢失] ⚠️  提前发送信号（没有线程在等待）" << std::endl;
            lost_cv.notify_one(); // 这个信号会丢失！
        }
        
        std::cout << "[信号丢失] 发送者线程结束" << std::endl;
    };
    
    // 信号丢失的等待者（后于发送者执行）
    auto lost_signal_waiter = []() {
        // 延迟启动，确保发送者先执行
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        
        std::cout << "[信号丢失] 等待者线程启动（信号已经丢失了）" << std::endl;
        
        std::unique_lock<std::mutex> lock(lost_mtx);
        
        // 检查条件，如果使用while循环，会发现条件已经满足
        if (!lost_ready) {
            std::cout << "[信号丢失] 开始等待信号..." << std::endl;
            
            // 设置超时，避免无限等待
            auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
            if (lost_cv.wait_until(lock, timeout) == std::cv_status::timeout) {
                std::cout << "[信号丢失] ⚠️  等待超时！信号已经丢失了！" << std::endl;
            }
        } else {
            std::cout << "[信号丢失] 条件已经满足，无需等待" << std::endl;
        }
    };
    
    std::thread t1(lost_signal_sender);
    std::thread t2(lost_signal_waiter);
    
    t1.join();
    t2.join();
    
    // 重置状态
    lost_ready = false;
    std::cout << "[信号丢失] 演示结束\n" << std::endl;
}

// ==================== 正确实现演示 ====================
void demonstrate_correct_usage()
{
    std::cout << "=== 正确使用条件变量演示 ===" << std::endl;
    std::cout << "解决方案：使用while循环 + 条件检查 + 适当的同步" << std::endl;
    
    std::mutex correct_mtx;
    std::condition_variable correct_cv;
    bool correct_ready = false;
    
    auto correct_waiter = [&]() {
        std::unique_lock<std::mutex> lock(correct_mtx);
        std::cout << "[正确实现] 等待线程开始等待..." << std::endl;
        
        // 正确：使用while循环检查条件
        while (!correct_ready) {
            std::cout << "[正确实现] 条件不满足，进入等待" << std::endl;
            correct_cv.wait(lock);
            std::cout << "[正确实现] 被唤醒，重新检查条件..." << std::endl;
        }
        
        std::cout << "[正确实现] ✅ 条件满足，执行任务" << std::endl;
    };
    
    auto correct_notifier = [&]() {
        // 确保等待者先开始等待
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        
        {
            std::lock_guard<std::mutex> lock(correct_mtx);
            correct_ready = true;
            std::cout << "[正确实现] 设置条件并发送通知" << std::endl;
            correct_cv.notify_one();
        }
    };
    
    std::thread t1(correct_waiter);
    std::thread t2(correct_notifier);
    
    t1.join();
    t2.join();
    
    std::cout << "[正确实现] 演示结束\n" << std::endl;
}

int main()
{
    std::cout << "C++11 条件变量问题演示程序" << std::endl;
    std::cout << "================================\n" << std::endl;
    
    // 1. 演示虚假信号唤醒
    demonstrate_spurious_wakeup();
    
    // 2. 演示信号量丢失
    // demonstrate_lost_signal();
    
    // // 3. 演示正确用法
    // demonstrate_correct_usage();
    
    std::cout << "\n总结：" << std::endl;
    std::cout << "1. 虚假唤醒：总是使用while循环而不是if来检查条件" << std::endl;
    std::cout << "2. 信号丢失：确保在发送信号前有线程在等待，或使用条件变量配合布尔标志" << std::endl;
    std::cout << "3. 正确模式：while循环 + 条件检查 + 互斥锁保护" << std::endl;
    
    return 0;
}
